cmake_minimum_required(VERSION 2.8.5)

get_filename_component(SAMPLE_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
    # CMAKE_CONFIGURATION_TYPES only reliable if set before project(), and not from an include file
    set(CMAKE_CONFIGURATION_TYPES "Debug;RelWithAsserts;RelWithDebInfo" CACHE INTERNAL "Build configs")
    project(${SAMPLE_NAME})
endif()    

include(../AddSample.cmake)

#------------------------------------------
# Configure all the tests
#------------------------------------------
function(configureAtomicTests template)
    set(INT_SIZES 32)
    set(STATUSES "_pass")
    set(THREAD_COUNTS 1)
    set(EXTRA_SUFFIX "")

    foreach(param IN ITEMS ${ARGN})
        string(FIND ${param} "=" sepIndex)
        if(NOT ${sepIndex} LESS 0)
            math(EXPR valueIndex "${sepIndex} + 1")
            string(SUBSTRING ${param} 0 ${sepIndex} key)
            string(SUBSTRING ${param} ${valueIndex} -1 value)
            set(TEST_${key} ${value})
            set(EXTRA_SUFFIX ${EXTRA_SUFFIX}_${value})
        elseif(param STREQUAL DUAL_THREAD)
            set(THREAD_COUNTS 2)
        elseif(param STREQUAL VAR_THREAD)
            set(THREAD_COUNTS 1 2 3 4)
        elseif(param STREQUAL VAR_SIZE)
            set(INT_SIZES 8 16 32 64)
        elseif(param STREQUAL ALLOW_FAIL)
            set(STATUSES _pass _fail)
        endif()
    endforeach()

    foreach(TEST_INT_BITSIZE IN ITEMS ${INT_SIZES})
        if(${TEST_INT_BITSIZE} EQUAL 8)
            set(TEST_INT_BITSHIFT 3)
        elseif(${TEST_INT_BITSIZE} EQUAL 16)
            set(TEST_INT_BITSHIFT 4)
        elseif(${TEST_INT_BITSIZE} EQUAL 32)
            set(TEST_INT_BITSHIFT 5)
        elseif(${TEST_INT_BITSIZE} EQUAL 64)
            set(TEST_INT_BITSHIFT 6)
        endif()
        foreach(status IN ITEMS ${STATUSES})
            if(${status} STREQUAL "_pass")
                set(status "")
                set(TEST_FORCE_FAIL false)
            else()
                set(TEST_FORCE_FAIL true)
            endif()

            set(TEST_IDENTIFIER ${template}${TEST_INT_BITSIZE}${status}${EXTRA_SUFFIX})
            set(TEST_FUNC test${TEST_IDENTIFIER})
            configure_file(Test${template}.cpp.in generated/Test${TEST_IDENTIFIER}.cpp)

            set(TEST_ENTRY_FUNCS "${TEST_ENTRY_FUNCS}TestEntryFunc ${TEST_FUNC};\n")
            foreach(numThreads IN ITEMS ${THREAD_COUNTS})
                set(TEST_INFOS "${TEST_INFOS}    { \"${TEST_FUNC} x ${numThreads}\", ${TEST_FUNC}, ${numThreads}, ${TEST_FORCE_FAIL} },\n")
            endforeach()
        endforeach()
    endforeach()

    set(TEST_ENTRY_FUNCS ${TEST_ENTRY_FUNCS} PARENT_SCOPE)
    set(TEST_INFOS ${TEST_INFOS} PARENT_SCOPE)
endfunction()

set(TEST_ENTRY_FUNCS "")
set(TEST_INFOS "")
configureAtomicTests(Exchange      VAR_THREAD VAR_SIZE ALLOW_FAIL)
configureAtomicTests(LoadStore     DUAL_THREAD ALLOW_FAIL VAR_SIZE)
configureAtomicTests(ReturnValues  VAR_SIZE)
configureAtomicTests(Increment     VAR_THREAD VAR_SIZE)
configureAtomicTests(AddTriangle   VAR_THREAD VAR_SIZE)
configureAtomicTests(BitArray      VAR_THREAD VAR_SIZE DATA_SIZE=128)
configureAtomicTests(BitArray      VAR_THREAD VAR_SIZE DATA_SIZE=32768)
configureAtomicTests(MutexAcqRel   VAR_THREAD VAR_SIZE ALLOW_FAIL)
configureAtomicTests(StoreLoad     DUAL_THREAD ALLOW_FAIL)
configureAtomicTests(LinkedList    VAR_THREAD VAR_SIZE)
configure_file(AtomicTests.cpp.in generated/AtomicTests.cpp)

GetFilesWithSourceGroups(GLOB_RECURSE PROJECT_FILES ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/generated/*.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated/*.h)
GetFilesWithSourceGroups(GLOB TEMPLATE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR} *.cpp.in)
list(APPEND PROJECT_FILES ${TEMPLATE_SOURCES})
AddSampleTargetFromSources("${PROJECT_FILES}")
